package br.com.ac.fatureweb.utilitary;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.activation.DataHandler;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

/**
 * 
 * Classe responsável pelo envio de emails.
 * 
 * TODO Criar esse classe pegando as configurações e usuário, servidor e email
 * do bancos de dados.
 *
 */
@SuppressWarnings("all")
public class Email {

	private static final String IP_SERVIDOR_EMAIL = "Seu servidor de email.";

	private static final String EMAIL_REGEX = "^[\\w-]+(\\.[\\w-]+)*@([\\w-]+\\.)+[a-zA-Z]{2,7}$";

	private static final String EMAIL = "email@email.com.br";

	/**
	 * 
	 * @param mailServer
	 * @param assunto
	 * @param emailRementente
	 * @param emailDestinatario
	 * @param mensagem
	 */
	public static void enviarEmail(final String mailServer,
			final String assunto, final String emailRementente,
			final String emailDestinatario, final String mensagem) {
		try {
			final Properties mailProps = new Properties();

			// definição do mailserver
			mailProps.put("mail.smtp.host", mailServer);

			final Session mailSession = Session.getDefaultInstance(mailProps,
					null);

			/*
			 * As duas linhas seguintes de código, colocam no formato de
			 * endereços, supostamente válidos, de email os dados passados pelos
			 * parâmetros to e from.
			 */
			final InternetAddress destinatario = new InternetAddress(
					emailDestinatario);

			final InternetAddress remetente = new InternetAddress(
					emailRementente);
			/*
			 * As duas linhas de código a seguir, são responsáveis por setar os
			 * atributos e propriedas necessárias do objeto message para que o
			 * email seja enviado. inicialização do objeto Message.
			 */
			final Message message = new MimeMessage(mailSession);

			// Definição de quem está enviando o email.
			message.setFrom(remetente);

			/*
			 * define o(s) destinatário(s) e qual o tipo do destinatário. os
			 * possíveis tipos de destinatário: TO, CC, BCC.
			 */
			message.setRecipient(Message.RecipientType.TO, destinatario);

			message.setSentDate(new Date());

			// definição do assunto do email.
			message.setSubject(assunto);

			if (mensagem != null) {
				// definição do conteúdo da mensagem e do tipo da mensagem.
				message.setContent(mensagem.toString(),
						"text/html;  charset=ISO-8859-1");
			} else {
				message.setContent("", "text/html; charset=ISO-8859-1");
			}

			// a linha de código seguinte é a responsável pelo envio do email.
			Transport.send(message);
		} catch (final Exception e) {
			// Não foi possível enviar o email.
		}
	}

	/**
	 * 
	 * @param email
	 * @return
	 */
	public static boolean validarEmail(final String email) {
		// Definir a seqüência de padrão de e-mail
		final Pattern p = Pattern.compile(EMAIL_REGEX);
		// Match Joga seqüência de dados com o padrão
		final Matcher m = p.matcher(email);
		// Verifica se o Match jogado foi encontrado
		final boolean valido = m.matches();

		return valido;
	}

	/**
	 * 
	 * @param email
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static boolean validaDominioEmail(final String email)

	{
		try {
			final String dominio = getDominio(email);

			final java.util.Hashtable env = new java.util.Hashtable();
			env.put("java.naming.factory.initial",
					"com.sun.jndi.dns.DnsContextFactory");
			env.put("com.sun.jndi.dns.timeout.initial", "600");
			env.put("com.sun.jndi.dns.timeout.retries", "3");
			env.put("java.naming.provider.url", "dns:");

			final DirContext ictx = new InitialDirContext(env);
			// DNS record types MX:mail exchange record
			final javax.naming.directory.Attributes attrs = ictx.getAttributes(
					dominio, new String[] { "MX" });
			final Attribute attr = attrs.get("MX");
			final boolean retorno = attr != null && attr.size() > 0 ? true
					: false;
			ictx.close();
			return retorno;
		} catch (final NameNotFoundException e) {
			return false;
		} catch (final NamingException e) {
			return true;
		} catch (final Exception e) {
			return true;
		}
	}

	/**
	 * 
	 * @param dominio
	 * @param ictx
	 * @param attr
	 * @return
	 * @throws NamingException
	 */
	private static List<String> getListIpDominio(final String dominio,
			final DirContext ictx, Attribute attr) throws NamingException {
		javax.naming.directory.Attributes attrs;

		// DNS record types A:address record
		attrs = ictx.getAttributes(dominio, new String[] { "A" });
		attr = attrs.get("A");

		final List<String> result = new ArrayList<String>();
		if (attr != null && attr.size() > 0) {
			final NamingEnumeration e = attr.getAll();

			while (e.hasMore()) {
				result.add((String) e.next());
			}
		}
		return result;
	}

	/**
	 * 
	 * @param email
	 * @return
	 */
	public static String getDominio(final String email) {
		int pos = email.indexOf('@');

		if (pos == -1) {
			return "";
		}
		final String domain = email.substring(++pos);

		return domain;
	}

	/**
	 * 
	 * @param assunto
	 * @param emailDestinatario
	 * @param mensagem
	 * @return
	 */
	public static Boolean enviarEmailEvalidar(final String assunto,
			final String emailDestinatario, final String mensagem) {
		final String mailServer = IP_SERVIDOR_EMAIL;
		final String emailRementente = EMAIL;

		try {
			final Properties mailProps = new Properties();

			// definição do mailserver
			mailProps.put("mail.smtp.host", mailServer);

			final Session mailSession = Session.getDefaultInstance(mailProps,
					null);

			/*
			 * As duas linhas seguintes de código, colocam no formato de
			 * endereços, supostamente válidos, de email os dados passados pelos
			 * parâmetros to e from.
			 */
			final InternetAddress destinatario = new InternetAddress(
					emailDestinatario);

			final InternetAddress remetente = new InternetAddress(
					emailRementente, "ATENDIMENTO CAGECE");
			/*
			 * As duas linhas de código a seguir, são responsáveis por setar os
			 * atributos e propriedas necessárias do objeto message para que o
			 * email seja enviado. inicialização do objeto Message.
			 */
			final Message message = new MimeMessage(mailSession);

			// Definição de quem está enviando o email.
			message.setFrom(remetente);

			/*
			 * define o(s) destinatário(s) e qual o tipo do destinatário. os
			 * possíveis tipos de destinatário: TO, CC, BCC.
			 */
			message.setRecipient(Message.RecipientType.TO, destinatario);

			message.setSentDate(new Date());

			// definição do assunto do email.
			message.setSubject(assunto);

			if (mensagem != null) {
				// definição do conteúdo da mensagem e do tipo da mensagem.
				message.setContent(mensagem.toString(),
						"text/html;  charset=ISO-8859-1");
			} else {
				message.setContent("", "text/html; charset=ISO-8859-1");
			}

			// a linha de código seguinte é a responsável pelo envio do email.
			Transport.send(message);
		} catch (final Exception e) {
			// Return error
			return false;
		}
		// Message is send
		return true;
	}

	/**
	 * 
	 * @param mailServer
	 * @param assunto
	 * @param emailRementente
	 * @param emailDestinatario
	 * @param mensagem
	 * @param anexo
	 * @param nomeArquivoAnexo
	 */
	public static void enviarEmail(String mailServer, final String assunto,
			final String emailRementente, final String emailDestinatario,
			final String mensagem, final byte[] anexo,
			final String nomeArquivoAnexo) {
		try {
			final Properties mailProps = new Properties();
			if (mailServer == null) {
				mailServer = IP_SERVIDOR_EMAIL;
			}

			// definição do mailserver
			mailProps.put("mail.smtp.host", mailServer);

			final Session mailSession = Session.getDefaultInstance(mailProps,
					null);

			/*
			 * As duas linhas seguintes de código, colocam no formato de
			 * endereços, supostamente válidos, de email os dados passados pelos
			 * parâmetros to e from.
			 */
			final InternetAddress destinatario = new InternetAddress(
					emailDestinatario);

			final InternetAddress remetente = new InternetAddress(
					emailRementente);
			/*
			 * As duas linhas de código a seguir, são responsáveis por setar os
			 * atributos e propriedas necessárias do objeto message para que o
			 * email seja enviado. inicialização do objeto Message.
			 */
			final Message message = new MimeMessage(mailSession);

			// Definição de quem está enviando o email.
			message.setFrom(remetente);

			/*
			 * define o(s) destinatário(s) e qual o tipo do destinatário. os
			 * possíveis tipos de destinatário: TO, CC, BCC.
			 */
			message.setRecipient(Message.RecipientType.TO, destinatario);

			message.setSentDate(new Date());

			// definição do assunto do email.
			message.setSubject(assunto);

			message.setHeader("Content-Type", "text/plain; charset=UTF-8");
			message.setHeader("Content-Transfer-Encoding", "quoted-printable");

			final Multipart corpo = new MimeMultipart();

			// final InternetHeaders headers = new InternetHeaders();
			//
			// headers.addHeader("Content-Type", "application/pdf");

			final MimeBodyPart msg = new MimeBodyPart();

			msg.setContent(mensagem, "text/plain; charset=UTF-8");

			final MimeBodyPart parAnexo = new MimeBodyPart();

			parAnexo.setDataHandler(new DataHandler(new ByteArrayDataSource(
					anexo, "aplication/pdf")));

			parAnexo.setFileName(nomeArquivoAnexo + ".pdf");

			corpo.addBodyPart(msg);
			corpo.addBodyPart(parAnexo);

			message.setContent(corpo);

			// a linha de código seguinte é a responsável pelo envio do email.
			Transport.send(message);
		} catch (final Exception e) {
			// Não foi possível enviar o email.
		}
	}

	/**
	 * 
	 * @param mailServer
	 * @param assunto
	 * @param emailRementente
	 * @param emailDestinatarios
	 * @param emailDestinatariosCC
	 * @param mensagem
	 * @param anexo
	 * @param nomeArquivoAnexo
	 */
	public static void enviarEmail(final String mailServer,
			final String assunto, final String emailRementente,
			final List<String> emailDestinatarios,
			final List<String> emailDestinatariosCC, final String mensagem,
			final byte[] anexo, final String nomeArquivoAnexo) {
		try {
			final Properties mailProps = new Properties();

			// definição do mailserver
			mailProps.put("mail.smtp.host", IP_SERVIDOR_EMAIL);

			final Session mailSession = Session.getDefaultInstance(mailProps,
					null);

			/*
			 * Alimenta as listas de destinatários
			 */
			final List<InternetAddress> emailsDest = new ArrayList<InternetAddress>();
			final List<InternetAddress> emailsDestCC = new ArrayList<InternetAddress>();
			InternetAddress email = null;

			if (!isBlankOrNullOrEmpty(emailDestinatarios)) {
				for (final String e : emailDestinatarios) {
					email = new InternetAddress(e);
					emailsDest.add(email);
				}

			}

			if (!isBlankOrNullOrEmpty(emailDestinatariosCC)) {
				for (final String e : emailDestinatariosCC) {
					email = new InternetAddress(e);
					emailsDestCC.add(email);
				}
			}

			final InternetAddress[] arrayEmailDest = emailsDest
					.toArray(new InternetAddress[emailsDest.size()]);
			final InternetAddress[] arrayEmailDestCC = emailsDestCC
					.toArray(new InternetAddress[emailsDestCC.size()]);

			/*
			 * As duas linhas seguintes de código, colocam no formato de
			 * endereços, supostamente válidos, de email os dados passados pelos
			 * parâmetros to e from.
			 */
			final InternetAddress remetente = new InternetAddress(
					emailRementente);
			/*
			 * As duas linhas de código a seguir, são responsáveis por setar os
			 * atributos e propriedas necessárias do objeto message para que o
			 * email seja enviado. inicialização do objeto Message.
			 */
			final Message message = new MimeMessage(mailSession);

			// Definição de quem está enviando o email.
			message.setFrom(remetente);

			/*
			 * define o(s) destinatário(s) e qual o tipo do destinatário. os
			 * possíveis tipos de destinatário: TO, CC, BCC.
			 */
			message.setRecipients(Message.RecipientType.TO, arrayEmailDest);

			message.setRecipients(Message.RecipientType.CC, arrayEmailDestCC);

			message.setSentDate(new Date());

			// definição do assunto do email.
			message.setSubject(assunto);

			message.setHeader("Content-Type", "text/plain; charset=UTF-8");
			message.setHeader("Content-Transfer-Encoding", "quoted-printable");

			final Multipart corpo = new MimeMultipart();

			final MimeBodyPart msg = new MimeBodyPart();

			msg.setContent(mensagem, "text/plain; charset=UTF-8");

			if (anexo != null && anexo.length != 0) {
				final MimeBodyPart parAnexo = new MimeBodyPart();

				parAnexo.setDataHandler(new DataHandler(
						new ByteArrayDataSource(anexo, "aplication/pdf")));

				parAnexo.setFileName(nomeArquivoAnexo + ".pdf");

				corpo.addBodyPart(parAnexo);
			}
			corpo.addBodyPart(msg);
			message.setContent(corpo, "text/plain; charset=UTF-8");

			// a linha de código seguinte é a responsável pelo envio do email.
			Transport.send(message);
		} catch (final Exception e) {

		}
	}

	private static boolean isBlankOrNullOrEmpty(List<String> lstParam) {
		return lstParam != null && lstParam.isEmpty();
	}

	/**
	 * 
	 * @param mailServer
	 * @param assunto
	 * @param emailRementente
	 * @param emailDestinatarios
	 * @param emailDestinatariosCC
	 * @param mensagem
	 */
	public static void enviarEmail(final String mailServer,
			final String assunto, final String emailRementente,
			final List<String> emailDestinatarios,
			final List<String> emailDestinatariosCC, final String mensagem) {
		try {
			final Properties mailProps = new Properties();

			// definição do mailserver
			mailProps.put("mail.smtp.host", IP_SERVIDOR_EMAIL);

			final Session mailSession = Session.getDefaultInstance(mailProps,
					null);

			/*
			 * Alimenta as listas de destinatários
			 */
			final List<InternetAddress> emailsDest = new ArrayList<InternetAddress>();
			final List<InternetAddress> emailsDestCC = new ArrayList<InternetAddress>();
			InternetAddress email = null;

			if (!isBlankOrNullOrEmpty(emailDestinatarios)) {
				for (final String e : emailDestinatarios) {
					email = new InternetAddress(e);
					emailsDest.add(email);
				}

			}

			if (!isBlankOrNullOrEmpty(emailDestinatariosCC)) {
				for (final String e : emailDestinatariosCC) {
					email = new InternetAddress(e);
					emailsDestCC.add(email);
				}
			}

			final InternetAddress[] arrayEmailDest = emailsDest
					.toArray(new InternetAddress[emailsDest.size()]);
			final InternetAddress[] arrayEmailDestCC = emailsDestCC
					.toArray(new InternetAddress[emailsDestCC.size()]);

			/*
			 * As duas linhas seguintes de código, colocam no formato de
			 * endereços, supostamente válidos, de email os dados passados pelos
			 * parâmetros to e from.
			 */
			final InternetAddress remetente = new InternetAddress(
					emailRementente);
			/*
			 * As duas linhas de código a seguir, são responsáveis por setar os
			 * atributos e propriedas necessárias do objeto message para que o
			 * email seja enviado. inicialização do objeto Message.
			 */
			final Message message = new MimeMessage(mailSession);

			// Definição de quem está enviando o email.
			message.setFrom(remetente);

			/*
			 * define o(s) destinatário(s) e qual o tipo do destinatário. os
			 * possíveis tipos de destinatário: TO, CC, BCC.
			 */
			message.setRecipients(Message.RecipientType.TO, arrayEmailDest);

			message.setRecipients(Message.RecipientType.CC, arrayEmailDestCC);

			message.setSentDate(new Date());

			// definição do assunto do email.
			message.setSubject(assunto);

			message.setContent(mensagem, "text/plain; charset=UTF-8");

			// a linha de código seguinte é a responsável pelo envio do email.
			Transport.send(message);
		} catch (final Exception e) {

		}
	}

	/**
	 * 
	 * @param mailServer
	 * @param assunto
	 * @param emailRementente
	 * @param emailDestinatarios
	 * @param emailDestinatariosCC
	 * @param mensagem
	 * @param anexos
	 * @param nomeArquivoAnexo
	 */
	public static void enviarEmail(final String mailServer,
			final String assunto, final String emailRementente,
			final List<String> emailDestinatarios,
			final List<String> emailDestinatariosCC, final String mensagem,
			final Map<String, byte[]> anexos, final String nomeArquivoAnexo) {
		try {
			final Properties mailProps = new Properties();

			// definição do mailserver
			mailProps.put("mail.smtp.host", IP_SERVIDOR_EMAIL);

			final Session mailSession = Session.getDefaultInstance(mailProps,
					null);

			/*
			 * Alimenta as listas de destinatários
			 */
			final List<InternetAddress> emailsDest = new ArrayList<InternetAddress>();
			final List<InternetAddress> emailsDestCC = new ArrayList<InternetAddress>();
			InternetAddress email = null;

			if (!isBlankOrNullOrEmpty(emailDestinatarios)) {
				for (final String e : emailDestinatarios) {
					email = new InternetAddress(e);
					emailsDest.add(email);
				}

			}

			if (!isBlankOrNullOrEmpty(emailDestinatariosCC)) {
				for (final String e : emailDestinatariosCC) {
					email = new InternetAddress(e);
					emailsDestCC.add(email);
				}
			}

			final InternetAddress[] arrayEmailDest = emailsDest
					.toArray(new InternetAddress[emailsDest.size()]);
			final InternetAddress[] arrayEmailDestCC = emailsDestCC
					.toArray(new InternetAddress[emailsDestCC.size()]);

			/*
			 * As duas linhas seguintes de código, colocam no formato de
			 * endereços, supostamente válidos, de email os dados passados pelos
			 * parâmetros to e from.
			 */
			final InternetAddress remetente = new InternetAddress(
					emailRementente);
			/*
			 * As duas linhas de código a seguir, são responsáveis por setar os
			 * atributos e propriedas necessárias do objeto message para que o
			 * email seja enviado. inicialização do objeto Message.
			 */
			final Message message = new MimeMessage(mailSession);

			// Definição de quem está enviando o email.
			message.setFrom(remetente);

			/*
			 * define o(s) destinatário(s) e qual o tipo do destinatário. os
			 * possíveis tipos de destinatário: TO, CC, BCC.
			 */
			message.setRecipients(Message.RecipientType.TO, arrayEmailDest);

			message.setRecipients(Message.RecipientType.CC, arrayEmailDestCC);

			message.setSentDate(new Date());

			// definição do assunto do email.
			message.setSubject(assunto);

			message.setHeader("Content-Type", "text/plain; charset=UTF-8");
			message.setHeader("Content-Transfer-Encoding", "quoted-printable");

			final Multipart corpo = new MimeMultipart();

			final MimeBodyPart msg = new MimeBodyPart();

			msg.setContent(mensagem, "text/plain; charset=UTF-8");

			final Set<String> keysAnexos = anexos.keySet();
			for (final String key : keysAnexos) {
				final byte[] anexo = anexos.get(key);

				final MimeBodyPart parAnexo = new MimeBodyPart();

				parAnexo.setDataHandler(new DataHandler(
						new ByteArrayDataSource(anexo, "aplication/pdf")));

				parAnexo.setFileName(key + "_" + nomeArquivoAnexo + ".pdf");

				corpo.addBodyPart(parAnexo);
			}
			corpo.addBodyPart(msg);
			message.setContent(corpo, "text/plain; charset=UTF-8");

			// a linha de código seguinte é a responsável pelo envio do email.
			Transport.send(message);
		} catch (final Exception e) {

		}
	}

	// TODO Pegar valores do banco, quando terminar apagar os outros métodos.
	public static void enviarEmailGmail() {

		/*
		 * java.net.UnknownHostException: smtp.gmail.com Some hit the
		 * UnknownHostException: smtp.gmail.com, try ping smtp.gmail.com and
		 * make sure you got a response (able to access). Often times, your
		 * connection may block by your firewall or proxy behind.
		 */

		Properties props = new Properties();
		props.put("mail.smtp.host", "smtp.gmail.com");
		props.put("mail.smtp.socketFactory.port", "465");
		props.put("mail.smtp.socketFactory.class",
				"javax.net.ssl.SSLSocketFactory");
		props.put("mail.smtp.auth", "true");
		props.put("mail.smtp.port", "465");

		Session session = Session.getDefaultInstance(props,
				new javax.mail.Authenticator() {
					protected PasswordAuthentication getPasswordAuthentication() {
						return new PasswordAuthentication("username",
								"password");
					}
				});

		try {

			Message message = new MimeMessage(session);
			message.setFrom(new InternetAddress("from@no-spam.com"));
			message.setRecipients(Message.RecipientType.TO,
					InternetAddress.parse("to@no-spam.com"));
			message.setSubject("Testing Subject");
			message.setText("Dear Mail Crawler,"
					+ "\n\n No spam to my email, please!");

			Transport.send(message);

			System.out.println("Done");

		} catch (MessagingException e) {
			throw new RuntimeException(e);
		}
	}

}
